package cn.huobi.basic.service.impl;

import cn.huobi.basic.config.BussinessException;
import cn.huobi.basic.constant.BaseConstant;
import cn.huobi.basic.dto.EmailCodeDto;
import cn.huobi.basic.dto.GetSmsCodeDto;
import cn.huobi.basic.dto.PhoneSmsCodeDto;
import cn.huobi.basic.dto.SmsCodeLoginDto;
import cn.huobi.basic.service.VerifyCodeService;
import cn.huobi.basic.util.EmailUtil;
import cn.huobi.basic.util.SendSmsUtil;
import cn.huobi.basic.util.StrUtils;
import cn.huobi.basic.util.VerifyCodeUtils;
import cn.huobi.user.domain.Logininfo;
import cn.huobi.user.domain.User;
import cn.huobi.user.mapper.LogininfoMapper;
import cn.huobi.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    /**
     * 获取图形验证码
     * @param uuidKey
     * @return
     */
    @Override
    public String getImageCode(String uuidKey) {
        // 获取随机数
        String randomString = StrUtils.getComplexRandomString(4);
        // 存入Redis
        redisTemplate.opsForValue().set(uuidKey,randomString,3, TimeUnit.MINUTES);
        // 生成图形验证码
        return VerifyCodeUtils.VerifyCode(100,35,randomString);
    }

    /**
     * 发送手机验证码
     */
    @Override
    public void smsCode(PhoneSmsCodeDto phoneSmsCodeDto) {
        // 判断参数是否为空 注解判断
        /*
         * 验证过手机号是否格式正确
         * /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
         */
        String regex = "^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$";
        if (!(phoneSmsCodeDto.getPhone()).matches(regex)){
            throw new BussinessException("请输入正确的手机号");
        }
        /*
         * 判断是 注册账号 还是 绑定手机号
         */
        if("register".equals(phoneSmsCodeDto.getType())){
            /*
             * 判断图形验证码是否正确
             */
            String imageCode = (String) redisTemplate.opsForValue().get(phoneSmsCodeDto.getImageCodeKey());
            if (StringUtils.isBlank(imageCode) || !imageCode.equalsIgnoreCase(phoneSmsCodeDto.getImageCodeValue())){
                throw new BussinessException("图形验证码错误，请重新输入！");
            }
            /*
             * 判断手机号是否已经注册
             */
            User user = userMapper.findByPhone(phoneSmsCodeDto.getPhone());
            if (user != null){
                throw new BussinessException("手机号已被注册，请直接登录！");
            }
            String smsCode = this.getVerifyCode(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE, phoneSmsCodeDto.getPhone()));
            //sendSmsCode(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE,phoneSmsCodeDto.getPhone()));

        }else if ("binder".equals(phoneSmsCodeDto.getType())){
            String smsCode = this.getVerifyCode(String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE, phoneSmsCodeDto.getPhone()));
            //SendSmsUtil.sendSms(phoneSmsCodeDto.getPhone(),"您好，你的注册验证码为"+smsCode+"，5分钟内有效。");
        }else {
            // 判断手机号是否存在
//            Logininfo logininfo = logininfoMapper.findByUsername(phoneSmsCodeDto.getPhone(), phoneSmsCodeDto.getType());
//            if (logininfo == null){
//                throw new BussinessException("手机号错误");
//            }
            String redisKey = String.format(BaseConstant.VerfityCodeCons.LOGIN_SMSCODE_PHONE, phoneSmsCodeDto.getPhone());
            String smsCode = this.getVerifyCode(redisKey);
        }


    }

    /**
     * 发送邮箱验证码
     */
    @Override
    public void emailCode(EmailCodeDto emailCodeDto) {
        // 判断参数是否为空 注解判断
        /*
         * 验证邮箱账号是否格式正确
         */
        String regex = "/^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$/";
        if (!(emailCodeDto.getEmail()).matches(regex)){
            throw new BussinessException("请输入正确格式的邮箱账号");
        }
        /*
         * 判断图形验证码是否正确
         */
        String imageCode = (String) redisTemplate.opsForValue().get(emailCodeDto.getImageCodeKey());
        if (StringUtils.isBlank(imageCode) || !imageCode.equalsIgnoreCase(emailCodeDto.getImageCodeValue())){
            throw new BussinessException("图形验证码错误");
        }
        /*
         * 判断该邮箱是否被注册过
         */
        User user = userMapper.findBYEmail(emailCodeDto.getEmail());
        if (user != null){
            throw new BussinessException("该邮箱账号已被注册，请直接登录！");
        }
        /*
         * 判断验证码发送时间是否大于60s
         * redis中 key：register:emailcode:email  value：验证码
         */
//        String redisEmailCode = (String) redisTemplate.opsForValue().get(
//                String.format(BaseConstant.VerfityCodeCons.REGISTER_EMAILCODE_EMAIL, emailCodeDto.getEmail()));
//        String emailCode = "";
//        if (StringUtils.isNotBlank(redisEmailCode)){
//            // 校验是否大于60s
//            String[] split = emailCode.split(":");
//            emailCode = split[0];
//            // 获取当前时间
//            long nowTime = System.currentTimeMillis();
//            // 存入Redis中的时间
//            Long redisTime = Long.valueOf(split[1]);
//            if (nowTime - redisTime < 60*1000){
//                throw new BussinessException("操作频繁，请稍后后重试");
//            }
//        }else {
//            emailCode = StrUtils.getRandomString(4);
//        }
//        log.info("验证码为：{}",emailCode);
//        /*
//         * 存到Redis中
//         */
//        redisTemplate.opsForValue().set(
//                String.format(BaseConstant.VerfityCodeCons.REGISTER_EMAILCODE_EMAIL,emailCodeDto.getEmail()),
//                emailCode,5,TimeUnit.MINUTES);
        // 发送邮箱验证码
        String redisKey = String.format(BaseConstant.VerfityCodeCons.REGISTER_EMAILCODE_EMAIL, emailCodeDto.getEmail());
        String emailCode = this.getVerifyCode(redisKey);
        String text = "<h1>你好，你的邮箱注册验证码为："+ emailCode +"，5分钟内有效！</h1>";
        EmailUtil.sendEmail("宠物之家",text,emailCodeDto.getEmail());
    }

    /**
     * 发送短信登录验证码
     */
    @Override
    public void smsCodeLogin(SmsCodeLoginDto smsCodeLoginDto) {
        // 判断手机号是否存在
        Logininfo logininfo = logininfoMapper.findByUsername(smsCodeLoginDto.getPhone(), smsCodeLoginDto.getType());
        if (logininfo == null){
            throw new BussinessException("手机号错误");
        }
//        // 判断获取时间是否大于六十秒
//        String redisSmsCode = (String) redisTemplate.opsForValue().get(
//                String.format(BaseConstant.VerfityCodeCons.LOGIN_SMSCODE_PHONE, smsCodeLoginDto.getPhone()));
//        String smsCode = "";
//        if (StringUtils.isNotBlank(redisSmsCode)){
//            String[] split = redisSmsCode.split(":");
//            smsCode = split[0];
//            // 获去当前时间
//            long nowTime = System.currentTimeMillis();
//            // 获取存入redis的时间
//            Long oldTime = Long.valueOf(split[1]);
//            if (nowTime - oldTime < 60*1000){
//                throw new BussinessException("操作频繁，请稍后后重试");
//            }
//        }else {
//            smsCode = StrUtils.getRandomString(4);
//        }
//        // 打印短信验证码
//        log.info("验证码为：{}",smsCode);
//        // 将验证码存入redis中
//        String redisValue = smsCode + ":" + System.currentTimeMillis();
//        redisTemplate.opsForValue().set(
//                String.format(BaseConstant.VerfityCodeCons.LOGIN_SMSCODE_PHONE,smsCodeLoginDto.getPhone())
//                ,redisValue,5,TimeUnit.MINUTES);
        String redisKey = String.format(BaseConstant.VerfityCodeCons.LOGIN_SMSCODE_PHONE, smsCodeLoginDto.getPhone());
        String smsCode = this.getVerifyCode(redisKey);
        // 发送验证码
        //SendSmsUtil.sendSms(smsCodeLoginDto.getPhone(),"您好，你的登录验证码为"+smsCode+"，5分钟内有效。");
    }

    /**
     * 生成验证码
     */
    private String getVerifyCode(String redisKey) {
        /*
         * 判断短信发送时间是否大于60s
         * redis中 key：register:smscode:phone  value：验证码:时间戳
         * 如果当redis中有就发送原来的，没有就发送新的
         */
        // 从redis中存入的获取短信验证码
        String redisSmsCode = (String) redisTemplate.opsForValue().get(redisKey);
        String smsCode = "";
        if(StringUtils.isNotBlank(redisSmsCode)){
            // 方式二 不用在Redis中存入时间戳 获取key的剩余时间
//            Long expire = redisTemplate.getExpire(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE, TimeUnit.MINUTES);
//            if (expire >= 4){
//                throw new BussinessException("请稍后后重试");
//            }
            // 校验是否大于60s
            String[] split = redisSmsCode.split(":");
            smsCode = split[0];
            // 获取当前时间
            long nowTime = System.currentTimeMillis();
            // 存入Redis中的时间
            Long redisTime = Long.valueOf(split[1]);
            if (nowTime - redisTime < 60*1000){
                throw new BussinessException("操作频繁，请稍后后重试");
            }
        }else {
            /*
             * 生成验证码
             */
            smsCode = StrUtils.getRandomString(4);
        }
        // 打印短信验证码
        log.info("验证码为：{}",smsCode);
        /*
         * 存入Redis中
         */
        // 设置存入redis中的value
        String redisValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(redisKey,redisValue,5,TimeUnit.MINUTES);
        return smsCode;
        /*
         * 发送短信
         */
//        String[] split = redisKey.split(":");
//        System.out.println(split[2]);
//        SendSmsUtil.sendSms(split[2],"您好，你的注册验证码为"+smsCode+"，5分钟内有效。");
    }
}
